#pragma once

#include <iostream>
#include <queue>
#include <pthread.h>
#include "Log.hpp"
#include "Task.hpp"

#define NUM 6
class ThreadPool{
    private:
     int num;
     bool stop;
     std::queue<Task> task_queue;
     pthread_mutex_t lock;//互斥锁
     pthread_cond_t cond;//条件变量

    //构建线程池单例模式
    ThreadPool(int _num = NUM):num(_num),stop(false)
    {
            pthread_mutex_init(&lock, nullptr);
            pthread_cond_init(&cond, nullptr);
                    }
     ThreadPool(const ThreadPool &){}

    static ThreadPool *single_instance;
  public:
   static ThreadPool* getinstance()//线程安全版 两层判断
        {
            static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
            if(single_instance == nullptr){
                pthread_mutex_lock(&_mutex);
                if(single_instance == nullptr){
                    single_instance = new ThreadPool();
                    single_instance->InitThreadPool();
                }
                pthread_mutex_unlock(&_mutex);
            }
            return single_instance;
        }
 
  bool IsStop()//判断线程是否停止
  {
     return stop;
  }
  bool TaskQueueIsEmpty()//判断任务队列是否为空
        {
            return task_queue.size() == 0 ? true : false;
        }

  void ThreadWait()//当没有任务时，线程等待
  {
     pthread_cond_wait(&cond, &lock);
  }
  void ThreadWakeup()//唤醒线程
  {
    pthread_cond_signal(&cond);
  }
  void Lock()
  {
    pthread_mutex_lock(&lock);
  }
  void Unlock()
  {
    pthread_mutex_unlock(&lock);
  }
  static void*ThreadRoutine(void *args )//线程的回调函数，也是线程的历程，之后要执行的动作，这里要设置为静态的
  {
         ThreadPool *tp = (ThreadPool*)args;
            while(true){
                Task t;
                tp->Lock();
                while(tp->TaskQueueIsEmpty()){
                    tp->ThreadWait(); //当我醒来的时候，一定是占有互斥锁的！
                }
                tp->PopTask(t);
                tp->Unlock();
                t.ProcessOn();
          }           
  }
  bool InitThreadPool()//初始化线程
  {  
    for(int i=0;i<num;i++)
    {
        pthread_t tid;
        if(pthread_create(&tid,nullptr,ThreadRoutine,this)!=0)//创建线程失败
        {
            LOG(FATAL,"create thread pool error!");
            return false;
        }
    }
       LOG(INFO, "create thread pool success!"); //创建成功
        return true;

  }
  void PushTask(const Task &task)//往任务队列中插入任务
  {
    Lock();
            task_queue.push(task);
            Unlock();
            ThreadWakeup();
  }
  void PopTask(Task &task)//从任务队列中取出任务
  {
     task = task_queue.front();
            task_queue.pop();
  }
  ~ThreadPool()
  {
       pthread_mutex_destroy(&lock);
       pthread_cond_destroy(&cond);
  }  

};
ThreadPool* ThreadPool::single_instance = nullptr;